#pragma once
#include <mysql++/mysql++.h>
#include <string>
#include <vector>
#include <utility>
#include <time.h>

using namespace std;

typedef  pair<unsigned int, unsigned int> accountid_monitorid;

class DBLayer
{
public:
    DBLayer(void);
    ~DBLayer(void);
    bool Connect(   const string& db,
                    const string& host,
                    const unsigned int& port,
                    const string& username,
                    const string& password);

    bool Reconnect( const string& db,
                    const string& host,
                    const unsigned int& port,
                    const string& username,
                    const string& password);

    bool GetMonitorInfo(    unsigned int& uiMonitorID,
                            unsigned int& uiAccountID,
                            string& szMonitorTitle,
                            unsigned int& uiMonitorStatus, 
                            string& szUrl,
                            string& szReferenceUrl,
                            unsigned char& ucUserAgentType,
                            string& szUserAgent,
                            string& szHttpAuthInfo,
                            string& szCookiesData,
                            string& szFormContent,
                            string& szProxyAddrInfo,
                            string& szProxyAuthInfo,
                            string& szUserCharset,
                            string& szXPath,
                            unsigned int& uiTriggerType, 
                            string& szTriggerParams,
                            int& iHLFontColor,
                            int& iHLBkColor,
                            unsigned int& uiHLFontStyle,
                            string& szAlertEmails,
                            string& szAlertEmailsBcc,
                            unsigned int& uiAlertType,
                            unsigned char& ucAlertFormat,
                            int& iAlertAtTime,
                            int& iTimeZoneOffset);
    
    bool GetEmailInfo(  unsigned int& uiEmailID,
                        unsigned int& uiMonitorID,
                        string& szEmailFrom,
                        vector<string>& recipients,
                        string& szEmailBody);

    bool GetMonitorTriggerInfo(     const unsigned int& uiMonitorID,
                                    string& szXPath,
                                    unsigned int& uiTriggerType,
                                    string& szTriggerParams,
                                    string& szUserCharset);
    
    bool GetMonitorTitleInfo(  const unsigned int& uiMonitorID,
                               string& szUrl,
                               string& szTitle);

    bool GetMonitorEmailInfo(   const unsigned int& uiMonitorID,
                                string& szEmail,
                                string& szEmailBcc,
                                unsigned char& ucContentType);

    bool GetAccountEmailInfo(   const unsigned int& uiAccountID,
                                string& szEmail,
                                string& szEmailBcc,
                                unsigned char& ucContentType);

    bool GetLastDownloadedResource( const unsigned int& uiMonitorID,
                                    unsigned int& uiResourceID,
                                    string& szResource,
                                    string& szResponseHeader,
                                    string& szEffectiveUrl);

    bool GetDownloadedResource( const unsigned int& uiMonitorID,
                                const unsigned int& uiResourceID,
                                unsigned int& uiRealResourceID,
                                string& szResource,
                                string& szResponseHeader,
                                string& szEffectiveUrl);

    bool GetDiffCache( const unsigned int& uiResourceID1,
                       const unsigned int& uiResourceID2,
                       string& szDiffCache,
                       bool& bDiffCacheFinded);

    bool GetFeed( const unsigned int& uiMonitorID,
                  const unsigned int& uiFeedType,
                  string& szFeed);

    bool GetEmailTemplate( const string& szTemplateName,
                           string& szEmailSubject,
                           string& szTemplateText,
                           string& szEmailFrom,
                           string& szEmailTo,
                           string& szEmailCc,
                           string& szEmailBcc);

    bool GetAllNotActivatedAccounts(const unsigned long& ulPeriod,
                                    vector<unsigned int>& accounts);

    bool GetAllNotActivatedMonitors(const unsigned long& ulPeriod,
                                    vector<accountid_monitorid>& monitors);

    bool UpdateMonitorInfo( const unsigned int& uiMonitorID,
                            const unsigned int& uiContentType,
                            const unsigned int& uiLastAlertType,
                            const string& szTitle,
                            const string& szDomainName,
                            const string& szFavicon,
                            const string& szFaviconContentType);

    bool SetEmailStatus(   const unsigned int& uiEmailID,
                           const unsigned int& uiEmailStatus);

    bool SetMonitorStatus( const unsigned int& uiMonitorID,
                           const unsigned int& uiMonitorStatus);

    bool SaveEmailToStorage(    const unsigned int& uiMonitorID,
                                const unsigned int& uiAccountID,
                                string& szEmailFrom,
                                const vector<string>& recipients,
                                const int& iAlertAtTime,
                                const int& iTimeZoneOffset,
                                const string& szEmailBody,
                                const bool& bCompress);

    bool SaveResourceToStorage( const unsigned int& uiMonitorID,
                                const unsigned int& uiAccountID,
                                const unsigned int& uiTriggerType, 
                                const string& szEffectiveUrl,
                                const string& szResource,
                                const bool& bCompress,
                                const unsigned long& ulCurlCode,
                                const string& szCurlMessage,
                                const unsigned long& ulHttpResponseCode,
                                const string& szHttpResponseHeader,
                                const unsigned char& ucResourceStatus,
                                const unsigned int& uiQtyAdded,
                                const unsigned int& uiQtyDeleted,
                                const unsigned int& uiQtyTriggers,
                                const unsigned int& uiQtyAnchors,
                                unsigned int& uiResourceID);

    bool SaveDownloadStatistics( const unsigned int& uiMonitorID,
                                 const unsigned int& uiAccountID,
                                 const double& dTotalTime,                                
                                 const double& dDownloadSpeed,
                                 const unsigned int& uiDownloadSize,
                                 const unsigned char& ucResourceStatus);

    bool SaveDiffCache( const unsigned int& uiResourceID1,
                        const unsigned int& uiResourceID2,
                        const string& szDiffCache,
                        const double& dTotalTime,
                        const unsigned int& uiVersion);

    bool SaveFeed(   const unsigned int& uiMonitorID,
                     const unsigned int& uiFeedType,
                     const string& szFeed);

    bool NeedDeactivateMonitorByCurlCode(   const unsigned int& uiMonitorID,
                                            const unsigned long& ulCurlCode,
                                            const unsigned long& ulMaxErrorsCount,
                                            bool& bNeedDeactivate);
    
    bool NeedDeactivateMonitorByResponseCode(   const unsigned int& uiMonitorID,
                                                const unsigned long& ulResponseCode,
                                                const unsigned long& ulMaxErrorsCount,
                                                bool& bNeedDeactivate);    

    bool ClearEmailStorage(const unsigned long& ulPeriod);
    
    bool ClearDiffCache(const unsigned int& uiDiffVersion);

    bool DeleteAccount(const unsigned int& uiAccountID);

    bool DeleteMonitor(const unsigned int& uiMonitorID);

private:

    void NeedReconnect(const int& err);
    void ConvertStringToHexString(const unsigned char* buffer, unsigned long ulBufferSize, string& szHexString);
    bool BeginTransaction();
    bool CommitTransaction();
    bool RollBackTransaction();

    mysqlpp::Connection *connection;
    CRITICAL_SECTION criticalSection;
    std::vector<unsigned int> monitors_cache;
    std::vector<unsigned int> emails_cache;

    string szDBName;
    string szHost;
    unsigned int uiPort;
    string szUsername;
    string szPassword;
};

extern DBLayer *dbLayer;